using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CodeGenerationPipelineInterface
{
    public enum ManagedListExceptionType
    {
        DoesNotMeetMinimumRequirements,
        DoesNotMeetMaximumRequirements
    }

    public class ManagedListException : Exception
    {
        private static string FormatMessage(string itemNamePlural, string listName, ManagedListExceptionType type, int limit)
        {
            switch (type)
            {
                case ManagedListExceptionType.DoesNotMeetMinimumRequirements:
                    return string.Format("{0} does not meet the minimum requirement of at lease {1} {2}", listName, limit, itemNamePlural);
                case ManagedListExceptionType.DoesNotMeetMaximumRequirements:
                    return string.Format("{0} does not meet the maximum requirement of at most {1} {2}", listName, limit, itemNamePlural);
                default:
                    throw new Exception("Invalid ManagedListExceptionType");
            }
        }

        public ManagedListException(string itemNamePlural, string listName, ManagedListExceptionType type, int limit) : base(ManagedListException.FormatMessage(itemNamePlural, listName, type, limit))
        {
        }
    }

    public class ManagedList<T> : List<T>, IList<T>
    {
        public int MinItems { get; set; }
        public int MaxItems { get; set; }
        private string itemNamePlural;
        private string listName;

        public ManagedList(string itemNamePlural, string listName, int minItems, int maxItems)
        {
            this.MinItems = minItems;
            this.MaxItems = maxItems;

            this.itemNamePlural = itemNamePlural;
            this.listName = listName;
        }

        public void Validate()
        {
            if (this.Count > this.MaxItems)
            {
                throw new ManagedListException(itemNamePlural, listName, ManagedListExceptionType.DoesNotMeetMaximumRequirements, this.MaxItems);
            }
            else if (this.Count < this.MinItems)
            {
                throw new ManagedListException(itemNamePlural, listName, ManagedListExceptionType.DoesNotMeetMinimumRequirements, this.MinItems);
            }
        }

        public new void Add(T item)
        {
            if (this.Count == this.MaxItems)
            {
                throw new ManagedListException(itemNamePlural, listName, ManagedListExceptionType.DoesNotMeetMaximumRequirements, this.MaxItems);
            }

            base.Add(item);
        }
    }
}
